import org.newdawn.slick.*;
import org.newdawn.slick.util.FontUtils;
import org.newdawn.slick.command.*;

/**
 * Contains the main entry point for the game. Initializes stuff.
 * 
 * @author Gerrit Jamerson, CodeMonkeys
 * @version 4/4/13
 */
public class GameController extends BasicGame
{
    private static InputController inputController;
    private static LayerController layerController;
    private static GameContainer gameContainer;
    private static IGamemode gameMode;
    private static GameState gameState;
    private static GameType gameType;

    /**
     * The different states of the game.
     */
    public enum GameState
    {
        MAINMENU,
        INGAME
    }
    
    /**
     * The types of games that can be played.
     */
    public enum GameType
    {
        SINGLEPLAYER
    } //End enum

    /**
     * Returns the game container.
     */
    public static AppGameContainer getGameContainer()
    {
        return (AppGameContainer)gameContainer;
    } //End getGameContainer method
    
    /**
     * The main entry point that will create the Game Container
     */
    public static void main(String[] args)
    {
        gameState = GameState.MAINMENU;

        //Set ups the game container
        try
        {
            Settings.loadSettings();
            int resolutionX = Settings.getResolutionX();
            int resolutionY = Settings.getResolutionY();

            AppGameContainer app = new AppGameContainer(new GameController());
            gameContainer  = app;

            app.setDisplayMode(resolutionX, resolutionY, Settings.getFullscreen());
            app.start();
        } //End try
        catch (SlickException e)
        {
            System.out.println(e.getMessage());
        } //End catch

    } //End entry point

    /**
     * Constructs the game controller.
     */
    public GameController()
    {
        super("DDC");
    }

    /**
     * Returns the current game mode
     * 
     * @pre None
     * @param None
     * @return The gamemode
     * @post None
     */
    public static IGamemode getGameMode()
    {
        return gameMode;
    } //End getGameMode method

    /**
     * Returns the current game state
     * 
     * @pre None
     * @param None
     * @return The game state
     * @post None
     */
    public static GameState getGameState()
    {
        return gameState;
    } //End getGameState method

    /**
     * The initialize method. Called when the GameContainer has finished setting up.
     * This is where resources are loaded into the GameRegistry for later use.
     * Overloaded method from the BasicGame class.
     * 
     * @pre GameContainer must be created
     * @param gameContainer The GameContainer
     * @return void
     * @post Resources have been loaded
     */
    public void init(GameContainer gameContainer) throws SlickException
    {
        GameRegistry.loadFont("visitor1.ttf", "fntMain", 32f, true);
        GameRegistry.loadFont("visitor1.ttf", "fntNote", 16f, true);
        GameRegistry.loadSpriteSheet("archerwalk.png", "anim_ArcherWalk", 16, 16);
        GameRegistry.loadSpriteSheet("archerstand.png", "anim_ArcherStand", 16, 16);
        GameRegistry.loadImage("wall.png", "brickWall");
        MainMenuController.initialize(gameContainer);
        layerController = new LayerController();
        inputController = new InputController(gameContainer);
    } //End initialize

    /**
     * The update method. Called each step from the GameContainer.
     * This is where all game logic will be performed for each GameObject.
     * Overloaded from the BasicGame class.
     * 
     * @pre GameContainer must be created
     * @param gameContainer The GameContainer
     * @param intDelta The delta time since the last step
     * @return void
     * @post Resources have been loaded
     */
    public void update(GameContainer gameContainer, int intDelta) throws SlickException
    {
        switch(gameState)
        {
            case MAINMENU:
            MainMenuController.update(gameContainer, intDelta);
            break;
            
            case INGAME:
            LayerController.update(gameContainer, intDelta);
            gameMode.update(gameContainer, intDelta);
            break;
        } //End if
    } //End update method

    /**
     * The render method. Called each frame from the GameContainer.
     * This is where all game graphics will be drawn to the screen.
     * Overloaded from the BasicGame class.
     * 
     * @pre GameContainer must be created
     * @param gameContainer The GameContainer
     * @param graphics The graphics class used to draw to the screen
     * @return void
     * @post Resources have been loaded
     */
    public void render(GameContainer gameContainer, Graphics graphics) throws SlickException
    {
        switch(gameState)
        {
            case INGAME:
            LayerController.render(gameContainer, graphics);
            break;
            
            case MAINMENU:
            MainMenuController.render(gameContainer, graphics);
            break;
        } //End switch
    } //End render method

    /**
     * Returns the input controller.
     * @returns The InputController instance.
     */
    public static InputController getInputController()
    {
        return inputController;
    }

    /**
     * Starts the game with the given game type.
     */
    public static void startGame(GameType _gameType)
    {
        gameType = _gameType;
        gameState = GameState.INGAME;
        
        switch(gameType)
        {
            case SINGLEPLAYER:
            gameMode = new GMSingleplayer();
            break;
        } //End switch
        
        gameMode.initialize();
    } //End startGame method
    
    /**
     * Exits the game.
     * 
     * @pre None
     * @param None
     * @return Void
     * @post Game has exited.
     */
    public static void exitGame()
    {
        gameContainer.exit();
    } //End exitGame method
} //End GameController class
